﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace MathService.NeuralNetworks
{
    public class Neuron : INeuron
    {
        private readonly IList<INeuralInput> f_Imputs = new List<INeuralInput>();

        private NeuralActivationFunction f_ActivationFunction = x => Math.Sign(x);

        public IList<INeuralInput> Imputs { get { return f_Imputs; } }

        public double Value { get; private set; }

        public NeuralActivationFunction ActivationFunction
        {
            get { return f_ActivationFunction; }
            set
            {
                //if(value == null)
                //    throw new ArgumentNullException();
                Contract.Ensures(f_ActivationFunction != null, @"Функция активации не может быть пустой");
                Contract.EndContractBlock();
                f_ActivationFunction = value;
            }
        }

        public Neuron()
        {
            Contract.Ensures(f_ActivationFunction != null);
            Contract.Ensures(f_Imputs != null);
        }
        public Neuron(NeuralActivationFunction F)
        {
            Contract.Requires(F != null, @"Функция активации не может быть пустой");
            if(F == null)
                throw new ArgumentNullException();
            Contract.Ensures(f_ActivationFunction != null);
            Contract.EndContractBlock();
            f_ActivationFunction = F;
        }
        public Neuron(IList<INeuralInput> Inputs, NeuralActivationFunction F)
            : this(F)
        {
            Contract.Requires(Inputs != null, @"Список входов не может отсутствовать");
            if(Inputs == null)
                throw new ArgumentNullException();
            Contract.Ensures(f_Imputs != null);
            Contract.EndContractBlock();
            f_Imputs = Inputs;
        }

        public double GetValue()
        {
            var result = 0.0;
            for(var i = 0; i < f_Imputs.Count; i++)
                result += f_Imputs[i].WeightValue;
            return Value = f_ActivationFunction(result);
        }
    }
}